const { MapService } = require('../models');
const { Op } = require('sequelize');
const logger = require('../utils/logger');
const config = require('../config');

class MapServiceService {
  /**
   * 创建地图服务
   * @param {Object} data - 地图服务数据
   * @returns {Promise<MapService>} - 创建后的地图服务
   */
  async createMapService(data) {
    try {
      const mapService = await MapService.create(data);
      logger.info(`Map service created with ID: ${mapService.id}`);
      return mapService;
    } catch (error) {
      logger.error('Error creating map service:', error);
      throw error;
    }
  }

  /**
   * 获取地图服务
   * @param {Object} filters - 过滤条件
   * @returns {Promise<Array<MapService>>} - 地图服务列表
   */
  async getMapServices(filters = {}) {
    try {
      const where = {};
      if (filters.provider) {
        where.provider = filters.provider;
      }
      if (filters.status) {
        where.status = filters.status;
      }
      if (filters.search) {
        where[Op.or] = [
          { name: { [Op.like]: `%${filters.search}%` } },
          { description: { [Op.like]: `%${filters.search}%` } }
        ];
      }

      const mapServices = await MapService.findAll({ where });
      return mapServices;
    } catch (error) {
      logger.error('Error getting map services:', error);
      throw error;
    }
  }

  /**
   * 获取地图服务
   * @param {number} id - 地图服务ID
   * @returns {Promise<MapService>} - 地图服务
   */
  async getMapServiceById(id) {
    try {
      const mapService = await MapService.findByPk(id);
      if (!mapService) {
        throw new Error('Map service not found');
      }
      return mapService;
    } catch (error) {
      logger.error(`Error getting map service with ID ${id}:`, error);
      throw error;
    }
  }

  /**
   * 更新地图服务
   * @param {number} id - 地图服务ID
   * @param {Object} data - 更新数据
   * @returns {Promise<MapService>} - 更新后的地图服务
   */
  async updateMapService(id, data) {
    try {
      const mapService = await this.getMapServiceById(id);
      await mapService.update(data);
      logger.info(`Map service ${id} updated successfully`);
      return mapService;
    } catch (error) {
      logger.error(`Error updating map service ${id}:`, error);
      throw error;
    }
  }

  /**
   * 删除地图服务
   * @param {number} id - 地图服务ID
   * @returns {Promise<boolean>} - 删除结果
   */
  async deleteMapService(id) {
    try {
      const mapService = await this.getMapServiceById(id);
      await mapService.destroy();
      logger.info(`Map service ${id} deleted successfully`);
      return true;
    } catch (error) {
      logger.error(`Error deleting map service ${id}:`, error);
      throw error;
    }
  }

  /**
   * 更新地图服务状态
   * @param {number} id - 地图服务ID
   * @param {string} status - 状态
   * @returns {Promise<MapService>} - 更新后的地图服务
   */
  async updateMapServiceStatus(id, status) {
    try {
      const mapService = await this.getMapServiceById(id);
      await mapService.update({ status });
      logger.info(`Map service ${id} status updated to ${status}`);
      return mapService;
    } catch (error) {
      logger.error(`Error updating map service ${id} status:`, error);
      throw error;
    }
  }

  /**
   * 增加地图服务使用次数
   * @param {number} id - 地图服务ID
   * @returns {Promise<MapService>} - 更新后的地图服务
   */
  async incrementUsageCount(id) {
    try {
      const mapService = await this.getMapServiceById(id);
      await mapService.increment('usageCount');
      logger.info(`Map service ${id} usage count incremented`);
      
      // Check usage quota
      if (mapService.usageQuota && mapService.usageCount >= mapService.usageQuota) {
        await this.updateMapServiceStatus(id, 'inactive');
        logger.warn(`Map service ${id} deactivated due to reaching usage quota`);
      }
      
      return mapService;
    } catch (error) {
      logger.error(`Error incrementing map service ${id} usage count:`, error);
      throw error;
    }
  }

  /**
   * 重置地图服务使用次数
   * @param {number} id - 地图服务ID
   * @returns {Promise<MapService>} - 更新后的地图服务
   */
  async resetUsageCount(id) {
    try {
      const mapService = await this.getMapServiceById(id);
      await mapService.update({ usageCount: 0 });
      logger.info(`Map service ${id} usage count reset`);
      return mapService;
    } catch (error) {
      logger.error(`Error resetting map service ${id} usage count:`, error);
      throw error;
    }
  }

  /**
   * 获取地图服务配置
   * @param {string} provider - 地图服务提供商
   * @returns {Promise<Object>} - 地图服务配置
   */
  async getMapServiceConfig(provider) {
    try {
      const mapService = await MapService.findOne({
        where: {
          provider,
          status: 'active'
        }
      });

      if (!mapService) {
        throw new Error(`No active map service found for provider: ${provider}`);
      }

      return {
        apiKey: mapService.apiKey,
        config: mapService.config,
        provider: mapService.provider
      };
    } catch (error) {
      logger.error(`Error getting map service config for provider ${provider}:`, error);
      throw error;
    }
  }

  /**
   * 地理编码
   * @param {string} provider - 地图服务提供商
   * @param {string} address - 地址
   * @returns {Promise<Object>} - 地理编码结果
   */
  async geocode(provider, address) {
    try {
      const serviceConfig = await this.getMapServiceConfig(provider);
      // Implement geocoding logic for different providers
      switch (provider) {
        case 'tencent':
          return this.tencentGeocode(address, serviceConfig);
        case 'amap':
          return this.amapGeocode(address, serviceConfig);
        case 'tianditu':
          return this.tianDiTuGeocode(address, serviceConfig);
        default:
          throw new Error(`Unsupported map service provider: ${provider}`);
      }
    } catch (error) {
      logger.error(`Error geocoding address with provider ${provider}:`, error);
      throw error;
    }
  }

  /**
   * 反向地理编码
   * @param {string} provider - 地图服务提供商
   * @param {number} latitude - 纬度
   * @param {number} longitude - 经度
   * @returns {Promise<Object>} - 反向地理编码结果
   */
  async reverseGeocode(provider, latitude, longitude) {
    try {
      const serviceConfig = await this.getMapServiceConfig(provider);
      // Implement reverse geocoding logic for different providers
      switch (provider) {
        case 'tencent':
          return this.tencentReverseGeocode(latitude, longitude, serviceConfig);
        case 'amap':
          return this.amapReverseGeocode(latitude, longitude, serviceConfig);
        case 'tianditu':
          return this.tianDiTuReverseGeocode(latitude, longitude, serviceConfig);
        default:
          throw new Error(`Unsupported map service provider: ${provider}`);
      }
    } catch (error) {
      logger.error(`Error reverse geocoding coordinates with provider ${provider}:`, error);
      throw error;
    }
  }

  /**
   * 腾讯地图地理编码
   * @param {string} address - 地址
   * @param {Object} config - 配置
   * @returns {Promise<Object>} - 地理编码结果
   */
  async tencentGeocode(address, config) {
    // Implement Tencent Maps geocoding
    throw new Error('Not implemented');
  }

  /**
   * 高德地图地理编码
   * @param {string} address - 地址
   * @param {Object} config - 配置
   * @returns {Promise<Object>} - 地理编码结果
   */
  async amapGeocode(address, config) {
    // Implement AMap geocoding
    throw new Error('Not implemented');
  }

  /**
   * 天地图地理编码
   * @param {string} address - 地址
   * @param {Object} config - 配置
   * @returns {Promise<Object>} - 地理编码结果
   */
  async tianDiTuGeocode(address, config) {
    // Implement TianDiTu geocoding
    throw new Error('Not implemented');
  }

  /**
   * 腾讯地图反向地理编码
   * @param {number} latitude - 纬度
   * @param {number} longitude - 经度
   * @param {Object} config - 配置
   * @returns {Promise<Object>} - 反向地理编码结果
   */
  async tencentReverseGeocode(latitude, longitude, config) {
    // Implement Tencent Maps reverse geocoding
    throw new Error('Not implemented');
  }

  /**
   * 高德地图反向地理编码
   * @param {number} latitude - 纬度
   * @param {number} longitude - 经度
   * @param {Object} config - 配置
   * @returns {Promise<Object>} - 反向地理编码结果
   */
  async amapReverseGeocode(latitude, longitude, config) {
    // Implement AMap reverse geocoding
    throw new Error('Not implemented');
  }

  /**
   * 天地图反向地理编码
   * @param {number} latitude - 纬度
   * @param {number} longitude - 经度
   * @param {Object} config - 配置
   * @returns {Promise<Object>} - 反向地理编码结果
   */
  async tianDiTuReverseGeocode(latitude, longitude, config) {
    // Implement TianDiTu reverse geocoding
    throw new Error('Not implemented');
  }
}

module.exports = new MapServiceService(); 